<template>
  <div class="">
    <div class="content content--canvas">
				<h2 class="content__title">Shift</h2>
		</div>
  </div>
</template>
 
<script>
import { floor, rand, randIn, randRange, fadeIn, fadeOut, fadeInOut, dist, angle, lerp, HALF_PI, TAU, TO_RAD } from './js/util.js'
const { PI, cos, sin, abs, sqrt, pow, round, random, atan2 } = Math
export default {
  data () {
    return {
      circleCount: 150,
      circlePropCount: 8,
      circlePropsLength: 150 * 8,
      baseSpeed: 0.1,
      rangeSpeed: 1,
      baseTTL: 150,
      rangeTTL: 200,
      baseRadius: 100,
      rangeRadius: 200,
      rangeHue: 60,
      xOff: 0.0015,
      yOff: 0.0015,
      zOff: 0.0015,
      baseHue: 'hsla(0,0%,5%,1)',

      container: null,
      canvas: {
        a: document.createElement('canvas'),
        b: document.createElement('canvas')
      },
      ctx: null,
      circles: null,
      circleProps: null,
      simplex: null,
      baseHue: null,
    }
  },
  mounted() {
    this.init()
  },
  methods: {
    init() {
      this.createCanvas()
      this.resize()
      this.initCircles()
      this.draw()
    },

    initCircles() {
      this.circleProps = new Float32Array(this.circlePropsLength);
      this.simplex = new SimplexNoise();
      this.baseHue = 220;

      let i;

      for (i = 0; i < this.circlePropsLength; i += this.circlePropCount) {
        this.initCircle(i);
      }
    },
    initCircle(i) {
      let x, y, n, t, speed, vx, vy, life, ttl, radius, hue;

      x = rand(this.canvas.a.width);
      y = rand(this.canvas.a.height);
      n = this.simplex.noise3D(x * this.xOff, y * this.yOff, this.baseHue * this.zOff);
      t = rand(TAU);
      speed = this.baseSpeed + rand(this.rangeSpeed);
      vx = speed * cos(t);
      vy = speed * sin(t);
      life = 0;
      ttl = this.baseTTL + rand(this.rangeTTL);
      radius = this.baseRadius + rand(this.rangeRadius);
      hue = this.baseHue + n * this.rangeHue;

      this.circleProps.set([x, y, vx, vy, life, ttl, radius, hue], i);
    },
    updateCircles() {
      let i;
      this.baseHue++;
      for (i = 0; i < this.circlePropsLength; i += this.circlePropCount) {
        this.updateCircle(i);
      }
    },
    updateCircle(i) {
      let i2=1+i, i3=2+i, i4=3+i, i5=4+i, i6=5+i, i7=6+i, i8=7+i;
      let x, y, vx, vy, life, ttl, radius, hue;

      x = this.circleProps[i];
      y = this.circleProps[i2];
      vx = this.circleProps[i3];
      vy = this.circleProps[i4];
      life = this.circleProps[i5];
      ttl = this.circleProps[i6];
      radius = this.circleProps[i7];
      hue = this.circleProps[i8];

      this.drawCircle(x, y, life, ttl, radius, hue);

      life++;

      this.circleProps[i] = x + vx;
      this.circleProps[i2] = y + vy;
      this.circleProps[i5] = life;

      (this.checkBounds(x, y, radius) || life > ttl) && this.initCircle(i);
    },
    drawCircle(x, y, life, ttl, radius, hue) {
      this.ctx.a.save();
      this.ctx.a.fillStyle = `hsla(${hue},60%,30%,${fadeInOut(life,ttl)})`;
      this.ctx.a.beginPath();
      this.ctx.a.arc(x,y, radius, 0, TAU);
      this.ctx.a.fill();
      this.ctx.a.closePath();
      this.ctx.a.restore();
    },
    checkBounds(x, y, radius) {
      return (
        x < -radius ||
        x > this.canvas.a.width + radius ||
        y < -radius ||
        y > this.canvas.a.height + radius
      );
    },

    createCanvas() {
      this.container = document.querySelector('.content--canvas');
      this.canvas.b.style = `
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
      `;
      this.container.appendChild(this.canvas.b);
      this.ctx = {
        a: this.canvas.a.getContext('2d'),
        b: this.canvas.b.getContext('2d')
      };
    },
    resize() {
      const { innerWidth, innerHeight } = window;
      
      this.canvas.a.width = innerWidth;
      this.canvas.a.height = innerHeight;

      this.ctx.a.drawImage(this.canvas.b, 0, 0);

      this.canvas.b.width = innerWidth;
      this.canvas.b.height = innerHeight;
      
      this.ctx.b.drawImage(this.canvas.a, 0, 0);
    },
    render() {
      this.ctx.b.save();
      this.ctx.b.filter = 'blur(50px)';
      this.ctx.b.drawImage(this.canvas.a, 0, 0);
      this.ctx.b.restore();
    },
    draw() {
      this.ctx.a.clearRect(0, 0, this.canvas.a.width, this.canvas.a.height);
      this.ctx.b.fillStyle = this.backgroundColor;
      this.ctx.b.fillRect(0, 0, this.canvas.b.width, this.canvas.b.height);
      this.updateCircles();
      this.render();
      window.requestAnimationFrame(this.draw);
    },

  }
}
</script>
 
<style scoped lang="less">
 
</style>